package com.designoutput.ui.editors
{
	import com.designoutput.elements.BaseElement;
	import com.designoutput.elements.LineElement;
	import com.designoutput.enum.ToolType;
	import com.designoutput.event.ElementEvent;
	import com.designoutput.ui.editors.transformEditorClasses.ResizeHandle;
	import com.designoutput.ui.editors.transformEditorClasses.RotateHandle;
	import com.designoutput.ui.editors.transformEditorClasses.SkewHandle;
	import com.designoutput.ui.editors.transformEditorClasses.TransformBoxEvent;
	import com.designoutput.ui.editors.transformEditorClasses.TransformUtils;
	import com.designoutput.ui.editors.transformEditorClasses.TransformationInfo;
	import com.designoutput.utils.Globals;
	import com.designoutput.utils.MathUtils;
	import com.designoutput.utils.SnapUtils;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	
	[Event(name="transformed", type="com.designoutput.ui.editors.transformEditorClasses.TransformBoxEvent")]
	public class TransformEditor extends BaseEditor
	{
		//Handles
		protected var _topLeftHandle:ResizeHandle;
		protected var _topRightHandle:ResizeHandle;
		protected var _bottomLeftHandle:ResizeHandle;
		protected var _bottomRightHandle:ResizeHandle;
		protected var _topHandle:ResizeHandle;
		protected var _bottomHandle:ResizeHandle;
		protected var _leftHandle:ResizeHandle;
		protected var _rightHandle:ResizeHandle;
		
		protected var _rotateHandle:RotateHandle;
		
		protected var _topSkewHandle:SkewHandle;
		protected var _rightSkewHandle:SkewHandle;
		protected var _bottomSkewHandle:SkewHandle;
		protected var _leftSkewHandle:SkewHandle;
		//
		
		private var _resizingHandle:ResizeHandle;
		private var _skewingHandle:SkewHandle;
		private var _lastMousePoint:Point;
		
		private var _rectangle:Rectangle;
		private var _rotation:Number = 0;
		private var _skewX:Number = 0;
		private var _skewY:Number = 0;
		private var _scaleX:Number = 1;
		private var _scaleY:Number = 1;
		
		private var _elementsStates:Dictionary = new Dictionary();
		private var _rectangleState:Rectangle;
		private var _rotationState:Number;
		private var _skewXState:Number;
		private var _skewYState:Number;
		private var _scaleXState:Number = 1;
		private var _scaleYState:Number = 1;
		
		public function TransformEditor()
		{
			visible = false;
			
			mouseEnabled = false;
			
			_topSkewHandle = createSkewHandle();
			_rightSkewHandle = createSkewHandle();
			_bottomSkewHandle = createSkewHandle();
			_leftSkewHandle = createSkewHandle();
			
			_rightHandle = createResizeHandle(0);
			_bottomRightHandle = createResizeHandle(45);
			_bottomHandle = createResizeHandle(90);
			_bottomLeftHandle = createResizeHandle(135);
			_leftHandle = createResizeHandle(180);
			_topLeftHandle = createResizeHandle(225);
			_topHandle = createResizeHandle(270);
			_topRightHandle = createResizeHandle(315);		
			
			_rotateHandle = createRotateHandle();
			
			addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, false, 0, true);
			addEventListener(MouseEvent.ROLL_OUT, rollOutHandler, false, 0, true);
		}
		
		override protected function onElementAdded(element:BaseElement):void {
			super.onElementAdded(element);
			element.addEventListener(ElementEvent.TRANSFORM_CHANGED, elementTransformChanged, false, 0, true);	
		}
		
		override protected function onElementRemoved(element:BaseElement):void {
			super.onElementRemoved(element);
			element.removeEventListener(ElementEvent.TRANSFORM_CHANGED, elementTransformChanged, false);
		}
		
		private function elementTransformChanged(e:Event):void {
			if(selectedElements.length == 1){
				updateFromElements();
				draw();
			}
		}
		
		override protected function onElementsChanged():void {
			if(selectedElements.length == 0){
				visible = false;
				return;
			}
					
			visible = true;
			
			if(selectedElements.length == 1 && selectedElements[0] is LineElement)
			{
				_topRightHandle.visible = false;
				_bottomLeftHandle.visible = false;
				_topHandle.visible = false;
				_bottomHandle.visible = false;
				_leftHandle.visible = false;
				_rightHandle.visible = false;				
				_rotateHandle.visible = false;
				_topSkewHandle.visible = false;
				_rightSkewHandle.visible = false;
				_bottomSkewHandle.visible = false;
				_leftSkewHandle.visible = false;
			} else {
				_topRightHandle.visible = true;
				_bottomLeftHandle.visible = true;
				_topHandle.visible = true;
				_bottomHandle.visible = true;
				_leftHandle.visible = true;
				_rightHandle.visible = true;				
				_rotateHandle.visible = true;
				_topSkewHandle.visible = true;
				_rightSkewHandle.visible = true;
				_bottomSkewHandle.visible = true;
				_leftSkewHandle.visible = true;
			}
			
			updateFromElements();
			
			draw();
			
			saveState();
		}
		
		private function rollOutHandler(e:MouseEvent):void {
			Globals.cursorManager.setCursor(ToolType.None);
		}
		
		private function mouseMoveHandler(e:MouseEvent):void {
			updateCursor(e.target as DisplayObject);
		}
		
		private function updateCursor(handle:DisplayObject, mouseDown:Boolean = false):void {
			var toolType:String = ToolType.None;
			
			if(handle is ResizeHandle)
			{
				var middlePoint:Point = Point.interpolate(new Point(_topLeftHandle.x, _topLeftHandle.y), new Point(_bottomRightHandle.x, _bottomRightHandle.y), 0.5);
				var offset:Point = new Point(_rightHandle.x, _rightHandle.y).subtract(middlePoint);
				var additionalRotation:Number = MathUtils.radianToDegrees(Math.atan2(offset.y, offset.x));
				
				toolType = getResizeCursor((handle as ResizeHandle).angle + additionalRotation);
			}
			else if(handle is SkewHandle)
				toolType = getResizeCursor(MathUtils.radianToDegrees((handle as SkewHandle).radianAngle));
				
			else if(handle == _rotateHandle)
				toolType = mouseDown ? ToolType.HandleRotateOnPress : ToolType.HandleRotate;
				
			else if(handle == this)
				toolType = ToolType.ElementBody;
			
			Globals.cursorManager.setCursor(toolType);
		}
		
		private function getResizeCursor(rotation:Number):String {
			var r:Number = rotation;
			
			while(r < 0)
				r = r + 360;
			
			r = MathUtils.roundInterval(r, 45) % 360;
			
			switch(r){
				case 0 :
					return ToolType.HandleR;
				case 45 :
					return ToolType.HandleBR;
				case 90 :
					return ToolType.HandleB;
				case 135 :
					return ToolType.HandleBL;
				case 180 :
					return ToolType.HandleL;
				case 225 :
					return ToolType.HandleTL;
				case 270 :
					return ToolType.HandleT;
				case 315 :
					return ToolType.HandleTR;
			}
			
			throw new Error("Invalid Operation");
		}
		
		private function createResizeHandle(angle:Number):ResizeHandle
		{
			var handle:ResizeHandle = new ResizeHandle(angle);
			handle.addEventListener(MouseEvent.MOUSE_DOWN, resize_mouseDownHandler, false, 0, true);
			addChild(handle);
			return handle;
		}
		
		private function createRotateHandle():RotateHandle {
			var handle:RotateHandle = new RotateHandle();
			handle.addEventListener(MouseEvent.MOUSE_DOWN, rotate_mouseDownHandler, false, 0, true);
			addChild(handle);
			return handle;
		}
		
		private function createSkewHandle():SkewHandle {
			var skewHandle:SkewHandle = new SkewHandle();
			skewHandle.addEventListener(MouseEvent.MOUSE_DOWN, skew_mouseDownHandler, false, 0, true);
			addChild(skewHandle);
			return skewHandle;
		}
			
		override public function mouseDownOnElement(element:BaseElement):void {
			saveState();
			
			updateCursor(this);
			Globals.cursorManager.lock();
			
			stage.addEventListener(MouseEvent.MOUSE_MOVE, move_stageMouseMoveHandler, false, 0, true);
			stage.addEventListener(MouseEvent.MOUSE_UP, move_stageMouseUpHandler, false, 0, true);
		}
		
		private function move_stageMouseMoveHandler(e:MouseEvent):void {
			restoreStates();
			
			var currentPoint:Point = new Point(mouseX, mouseY);
			
			var offset:Point = currentPoint.subtract(_lastMousePoint);		
			doMove(offset.x, offset.y);
			
			draw();
		}
		
		private function move_stageMouseUpHandler(e:MouseEvent):void {
			Globals.cursorManager.unlock();
			
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, move_stageMouseMoveHandler, false);
			stage.removeEventListener(MouseEvent.MOUSE_UP, move_stageMouseUpHandler, false);
		}
		
		
		private function rotate_mouseDownHandler(e:MouseEvent):void {
			saveState();
			
			updateCursor(e.target as DisplayObject, true);
			Globals.cursorManager.lock();
			
			stage.addEventListener(MouseEvent.MOUSE_MOVE, rotate_stageMouseMoveHandler, false, 0, true);
			stage.addEventListener(MouseEvent.MOUSE_UP, rotate_stageMouseUpHandler, false, 0, true);
		}
		
		private function rotate_stageMouseMoveHandler(e:MouseEvent):void {
			restoreStates();
			
			var transformPoint:Point = new Point((_rectangle.left + _rectangle.right)/2, (_rectangle.top + _rectangle.bottom)/2);
			transformPoint = getTransformMatrix().transformPoint(transformPoint);
			
			var angle1:Number = MathUtils.round(MathUtils.radianToDegrees(Math.atan2(_lastMousePoint.y - transformPoint.y, _lastMousePoint.x - transformPoint.x)));
			var angle2:Number = MathUtils.round(MathUtils.radianToDegrees(Math.atan2(mouseY - transformPoint.y, mouseX - transformPoint.x)));
			
			doRotate(angle2 - angle1, transformPoint);
			
			draw();
		}
		
		private function rotate_stageMouseUpHandler(e:MouseEvent):void {
			Globals.cursorManager.unlock();
			
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, rotate_stageMouseMoveHandler, false);
			stage.removeEventListener(MouseEvent.MOUSE_UP, rotate_stageMouseUpHandler, false);
		}
		
		private function skew_mouseDownHandler(e:MouseEvent):void {
			saveState();
			
			updateCursor(e.target as DisplayObject);
			Globals.cursorManager.lock();
			
			_skewingHandle = e.target as SkewHandle;
			stage.addEventListener(MouseEvent.MOUSE_MOVE, skew_stageMouseMoveHandler, false, 0, true);
			stage.addEventListener(MouseEvent.MOUSE_UP, skew_stageMouseUpHandler, false, 0, true);
		}
		
		private function skew_stageMouseMoveHandler(e:MouseEvent):void {
			restoreStates();
			
			var transformPoint:Point = new Point((_rectangle.left + _rectangle.right)/2, (_rectangle.top + _rectangle.bottom)/2);
			transformPoint = getTransformMatrix().transformPoint(transformPoint);
			
			var offset:Point = new Point(mouseX, mouseY).subtract(_lastMousePoint);
			var offsetRadianAngle:Number = Math.atan2(offset.y, offset.x);
			
			var angle:Number = offset.length * Math.cos(offsetRadianAngle - _skewingHandle.radianAngle);
			
			if(angle > 60)
				angle = 60;
			else if(angle < -60)
				angle = -60;
			
			if(_skewingHandle == _topSkewHandle || _skewingHandle == _bottomSkewHandle)
				doSkew(angle, 0, transformPoint);
			else if(_skewingHandle == _leftSkewHandle || _skewingHandle == _rightSkewHandle)
				doSkew(0, angle, transformPoint);
			
			draw();
		}
		
		private function skew_stageMouseUpHandler(e:MouseEvent):void {
			Globals.cursorManager.unlock();
			
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, skew_stageMouseMoveHandler, false);
			stage.removeEventListener(MouseEvent.MOUSE_UP, skew_stageMouseUpHandler, false);
		}
		
		private function resize_mouseDownHandler(e:MouseEvent):void {
			saveState();
			
			updateCursor(e.target as DisplayObject);
			Globals.cursorManager.lock();
			
			_resizingHandle = e.target as ResizeHandle;
			
			stage.addEventListener(MouseEvent.MOUSE_MOVE, resize_stageMouseMoveHandler, false, 0, true);
			stage.addEventListener(MouseEvent.MOUSE_UP, resize_stageMouseUpHandler, false, 0, true);
		}
		
		private function resize_stageMouseMoveHandler(e:MouseEvent):void {
			restoreStates();
			
			var offset:Point = new Point(mouseX, mouseY).subtract(_lastMousePoint);			
			offset = getInverseTransformMatrix().deltaTransformPoint(offset);
			
			var dx:Number = 0;
			var dy:Number = 0;
			
			if(_resizingHandle != _topHandle && _resizingHandle != _bottomHandle)
				dx = offset.x;
			
			if(_resizingHandle != _leftHandle && _resizingHandle != _rightHandle)
				dy = offset.y;
			
			var transformPoint:Point = new Point();
			
			if(_resizingHandle == _topLeftHandle || _resizingHandle == _topHandle || _resizingHandle == _topRightHandle){
				transformPoint.y = _rectangle.bottom;				
				dy = -dy;
			} else if(_resizingHandle == _bottomLeftHandle || _resizingHandle == _bottomHandle || _resizingHandle == _bottomRightHandle){
				transformPoint.y = _rectangle.top;
			}
			
			if(_resizingHandle == _topLeftHandle || _resizingHandle == _leftHandle || _resizingHandle == _bottomLeftHandle){
				transformPoint.x = _rectangle.right;
				dx = -dx;
			} else if(_resizingHandle == _topRightHandle || _resizingHandle == _rightHandle || _resizingHandle == _bottomRightHandle){
				transformPoint.x = _rectangle.left;
			}
			
			transformPoint = getTransformMatrix().transformPoint(transformPoint);
			
			var scaleX:Number = 1 + (dx / _rectangle.width);
			var scaleY:Number = 1 + (dy / _rectangle.height);
			
			if(SnapUtils.snapEnabled)
				scaleX = scaleY = Math.min(scaleX, scaleY);
			
			doScale(scaleX, scaleY, transformPoint);
			
			draw();
		}
		
		private function resize_stageMouseUpHandler(e:MouseEvent):void {
			Globals.cursorManager.unlock();
			
			_resizingHandle = null;
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, resize_stageMouseMoveHandler, false);
			stage.removeEventListener(MouseEvent.MOUSE_UP, resize_stageMouseUpHandler, false);
		}
		
		private function draw():void {
			var m:Matrix = getTransformMatrix();
			
			var topLeft:Point = m.transformPoint(new Point(_rectangle.left, _rectangle.top));
			var topRight:Point = m.transformPoint(new Point(_rectangle.right, _rectangle.top));
			var bottomLeft:Point = m.transformPoint(new Point(_rectangle.left, _rectangle.bottom));
			var bottomRight:Point = m.transformPoint(new Point(_rectangle.right, _rectangle.bottom));
			
			var top:Point = m.transformPoint(new Point((_rectangle.left + _rectangle.right)/2, _rectangle.top));
			var bottom:Point = m.transformPoint(new Point((_rectangle.left + _rectangle.right)/2, _rectangle.bottom));
			var left:Point = m.transformPoint(new Point(_rectangle.left, (_rectangle.top + _rectangle.bottom)/2));
			var right:Point = m.transformPoint(new Point(_rectangle.right, (_rectangle.top + _rectangle.bottom)/2));
			
			var rotate:Point = m.transformPoint(new Point(_rectangle.right + 20, (_rectangle.top + _rectangle.bottom)/2));
			var middleTransformPoint:Point = m.transformPoint(Point.interpolate(_rectangle.topLeft, _rectangle.bottomRight, 0.5));
			
			graphics.clear();
			graphics.lineStyle(1, 0x000000);
			//graphics.beginFill(0, 0.1);
			graphics.moveTo(topLeft.x, topLeft.y);
			graphics.lineTo(topRight.x, topRight.y);
			graphics.lineTo(bottomRight.x, bottomRight.y);
			graphics.lineTo(bottomLeft.x, bottomLeft.y);
			graphics.lineTo(topLeft.x, topLeft.y);
			graphics.endFill();
			
			_topLeftHandle.x = topLeft.x;
			_topLeftHandle.y = topLeft.y;
			
			_topRightHandle.x = topRight.x;
			_topRightHandle.y = topRight.y;
			
			_bottomLeftHandle.x = bottomLeft.x;
			_bottomLeftHandle.y = bottomLeft.y;
			
			_bottomRightHandle.x = bottomRight.x;
			_bottomRightHandle.y = bottomRight.y;
			
			_topHandle.x = top.x;
			_topHandle.y = top.y;
			
			_bottomHandle.x = bottom.x;
			_bottomHandle.y = bottom.y;
			
			_leftHandle.x = left.x;
			_leftHandle.y = left.y;
			
			_rightHandle.x = right.x;
			_rightHandle.y = right.y;
			
			_rotateHandle.x = rotate.x;
			_rotateHandle.y = rotate.y;
			
			_topSkewHandle.setValues(topRight, topLeft);
			_rightSkewHandle.setValues(topRight, bottomRight);
			_bottomSkewHandle.setValues(bottomLeft, bottomRight);
			_leftSkewHandle.setValues(bottomLeft, topLeft);
		}
		
		private function getTransformMatrix():Matrix {
			var matrix:Matrix = new Matrix();
			matrix.translate(-_rectangle.x, -_rectangle.y);
			matrix.concat(getDeltaTransformMatrix());
			matrix.translate(_rectangle.x, _rectangle.y);
			return matrix;
		}
		
		private function getInverseTransformMatrix():Matrix {
			var matrix:Matrix = getTransformMatrix();
			matrix.invert();
			return matrix;
		}
		
		private function getDeltaTransformMatrix():Matrix {
			var matrix:Matrix = new Matrix();
			matrix.scale(_scaleX, _scaleY);
			if(_skewX != 0 || _skewY != 0)
			{
				safeSkewMatrix(matrix, _skewX, _skewY);
			} else {
				matrix.rotate(MathUtils.degreesToRadian(_rotation));
			}
			return matrix;
		}
		
		private function getInverseDeltaTransformMatrix():Matrix {
			var matrix:Matrix = getDeltaTransformMatrix();
			matrix.invert();
			return matrix;
		}
		
		private function skewMatrix(matrix:Matrix, skewX:Number, skewY:Number):void {
			var radianSkewX:Number = MathUtils.degreesToRadian(skewX);
			var radianSkewY:Number = MathUtils.degreesToRadian(skewY);
			
			matrix.concat(new Matrix(1, Math.tan(radianSkewY), Math.tan(radianSkewX), 1));
		}
		
		private function safeSkewMatrix(matrix:Matrix, skewX:Number, skewY:Number):void {
			var skewMat:Matrix = new Matrix();
			
			var radianSkewX:Number = MathUtils.degreesToRadian(skewX);
			var radianSkewY:Number = MathUtils.degreesToRadian(skewY);
			
			skewMat.a = Math.cos(radianSkewY);
			skewMat.b = Math.sin(radianSkewY);
			skewMat.c = -Math.sin(radianSkewX);
			skewMat.d = Math.cos(radianSkewX);
			
			matrix.concat(skewMat);
		}
		
		public function saveState():void {
			_lastMousePoint = new Point(mouseX, mouseY);
			
			_rectangleState = _rectangle.clone();
			_rotationState = _rotation;
			_skewXState = _skewX;
			_skewYState = _skewY;
			_scaleXState = _scaleX;
			_scaleYState = _scaleY;
			
			for each(var element:BaseElement in selectedElements)
				_elementsStates[element] = element.getReferencePoints();
		}
		
		public function restoreStates():void {
			_rectangle = _rectangleState.clone();
			_rotation = _rotationState;
			_skewX = _skewXState;
			_skewY = _skewYState;
			_scaleXState = _scaleX;
			_scaleYState = _scaleY;
			
			for each(var element:BaseElement in selectedElements)
				element.setReferencePoints(_elementsStates[element]);
		}
		
		public function move(dx:Number, dy:Number):void
		{
			saveState();
			doMove(dx, dy);
			draw();
			saveState();
		}
		
		private function doMove(dx:Number, dy:Number):void {
			var moveMatrix:Matrix = new Matrix();
			moveMatrix.translate(dx, dy);
			
			doTransform(moveMatrix);
		}
		
		private function doRotate(angle:Number, transformPoint:Point):void {
			var rotateMatrix:Matrix = new Matrix();
			rotateMatrix.translate(-transformPoint.x, -transformPoint.y);
			rotateMatrix.rotate(MathUtils.degreesToRadian(angle));
			rotateMatrix.translate(transformPoint.x, transformPoint.y);
			
			doTransform(rotateMatrix);
		}
		
		private function doSkew(skewX:Number, skewY:Number, transformPoint:Point):void {
			var matrix:Matrix = new Matrix();
			matrix.translate(-transformPoint.x, -transformPoint.y);
			matrix.concat(getInverseDeltaTransformMatrix());
			skewMatrix(matrix, skewX, skewY);
			matrix.concat(getDeltaTransformMatrix());
			matrix.translate(transformPoint.x, transformPoint.y);
			
			doTransform(matrix);
		}
		
		private function doScale(sx:Number, sy:Number, transformPoint:Point):void {
			var scaleMatrix:Matrix = new Matrix();
			scaleMatrix.translate(-transformPoint.x, -transformPoint.y);
			scaleMatrix.concat(getInverseDeltaTransformMatrix());
			scaleMatrix.scale(sx, sy);
			scaleMatrix.concat(getDeltaTransformMatrix());
			scaleMatrix.translate(transformPoint.x, transformPoint.y);
			
			doTransform(scaleMatrix);
		}
		
		public function doTransform(matrix:Matrix):void {
			transformElements(matrix);
			if(selectedElements.length > 1)
				transformTransformBox(matrix);
			else if(selectedElements.length == 1)
				updateFromElements();
			
			dispatchEvent( new TransformBoxEvent(TransformBoxEvent.TRANSFORMED) );
		}
		
		public function transformElements(matrix:Matrix):void {
			for each(var element:BaseElement in selectedElements){
				var pointsArray:Vector.<Point> = _elementsStates[element];
				var modifiedPointsArray:Vector.<Point> = new Vector.<Point>();
				for(var i:int = 0; i < pointsArray.length; i++){
					var p:Point = matrix.transformPoint(pointsArray[i]);
					modifiedPointsArray.push(p);
				}
				
				element.setReferencePoints(modifiedPointsArray);
			}
		}
		
		public function transformTransformBox(matrix:Matrix):void {
			var m:Matrix = getTransformMatrix();
			var myPoints:Vector.<Point> = new Vector.<Point>();
			myPoints.push(m.transformPoint(new Point(_rectangle.left, _rectangle.top)));
			myPoints.push(m.transformPoint(new Point(_rectangle.right, _rectangle.top)));
			myPoints.push(m.transformPoint(new Point(_rectangle.left, _rectangle.bottom)));
			
			for(var i:int = 0; i < myPoints.length; i++)
				myPoints[i] = matrix.transformPoint(myPoints[i]);
			
			var transformationInfo:TransformationInfo = TransformUtils.get3PointsTransformation(myPoints);
			_rectangle.x = transformationInfo.x;
			_rectangle.y = transformationInfo.y;
			_rectangle.width = transformationInfo.width;
			_rectangle.height = transformationInfo.height;
			_skewX = transformationInfo.skewX;
			_skewY = transformationInfo.skewY;
			_rotation = transformationInfo.rotation;
			_scaleX = transformationInfo.scaleX;
			_scaleY = transformationInfo.scaleY;
		}
		
		public function updateFromElements():void {
			if(selectedElements.length == 1){
				var target:BaseElement = selectedElements[0];
				
				_rectangle = new Rectangle(target.x, target.y, target.width, target.height);
				_rotation = target.rotation;
				_skewX = target.skewX;
				_skewY = target.skewY;
				_scaleX = target.scaleX;
				_scaleY = target.scaleY;
			} else {
				var selectedBounds:Rectangle = new Rectangle();
				
				for each(var element:BaseElement in selectedElements){
					var elementBounds:Rectangle = element.getBounds(this);
					selectedBounds = selectedBounds.union(elementBounds);
				}
				
				_rectangle = selectedBounds;
				_rotation = 0;
				_skewX = 0;
				_skewY = 0;
			}
		}
	}
}